﻿using System;
using Microsoft.Xna.Framework;
using SolarWinds.Cameras;
using SolarWinds.Input;
using Microsoft.Xna.Framework.Input;

namespace SolarWinds.Controllers
{
    public class CameraController : GameComponent
    {
        public Camera Camera { get; set; }

        public CameraController(Game game) : base(game)
        {
        }

        public override void Initialize()
        {
            base.Initialize();

            var input = (IInputManagerService)Game.Services.GetService(typeof(IInputManagerService));

            input.Mouse.ButtonPressed += MouseButtonPressed;
            input.Mouse.ButtonReleased += MouseButtonReleased;
            input.Mouse.Moved += MouseMoved;
            input.Mouse.WheelScrolled += MouseWheelScrolled;

            UpdateCameraPosition();
        }

        private float mRadius = 400.0f;
        private float mHRadians = (float)-Math.PI*0.5f;
        private float mVRadians = (float)Math.PI*0.4f;
        private float mRotateSpeed = 0.002f;
        private float mMoveSpeed = 1.0f;
        private float mTargetSpeed = 2.0f;
        
        private void UpdateCameraPosition ()
        {
            Vector3 position = Camera.Position;
            Vector3 target = Camera.Target;

            Camera.Position = new Vector3(target.X + (float)(mRadius * Math.Cos(mVRadians) * Math.Cos(mHRadians)),
                                          target.Y + (float)(mRadius * Math.Sin(mVRadians)),
                                          target.Z + (float)(mRadius * Math.Cos(mVRadians) * Math.Sin(mHRadians)));
        }

        public override void Update(GameTime gameTime)
        {
            var state = Keyboard.GetState();

            if (state.IsKeyDown(Keys.A))
            {
                Vector3 target = Camera.Target;

                target.X += mTargetSpeed;

                Camera.Target = target;
            }
            if (state.IsKeyDown(Keys.D))
            {
                Vector3 target = Camera.Target;

                target.X -= mTargetSpeed;

                Camera.Target = target;
            }

            if (state.IsKeyDown(Keys.W))
            {
                Vector3 target = Camera.Target;

                target.Z += mTargetSpeed;

                Camera.Target = target;
            }
            if (state.IsKeyDown(Keys.S))
            {
                Vector3 target = Camera.Target;

                target.Z -= mTargetSpeed;

                Camera.Target = target;
            }

            UpdateCameraPosition();
        }

        #region Mouse Control

        private bool mRightMouseButtonDown;

        private void MouseWheelScrolled(object sender, MouseEvent e)
        {
            mRadius -= e.RelativeWheelPosition * mMoveSpeed;

            UpdateCameraPosition();
        }

        void MouseMoved(object sender, MouseEvent e)
        {
            if (mRightMouseButtonDown)
            {
                mHRadians += e.RelativePosition.X * mRotateSpeed;
                mVRadians += e.RelativePosition.Y * mRotateSpeed;

                UpdateCameraPosition();
            }
        }

        void MouseButtonReleased(object sender, MouseEvent e)
        {
            if (e.Button == MouseButtons.Right)
            {
                mRightMouseButtonDown = false;
            } 
        }

        void MouseButtonPressed(object sender, MouseEvent e)
        {
            if (e.Button == MouseButtons.Right)
            {
                mRightMouseButtonDown = true;
            }
        }

        #endregion
    }
}
